package com.gitee.wsl.net.ssdp.description.model.xml


import com.gitee.wsl.logger.Logger
import com.gitee.wsl.logger.info
import com.gitee.wsl.net.ssdp.description.xml.XmlElement
import kotlin.properties.Delegates

/**
 * Detailed device description
 * @param urn           - reference to the UPnP Device Schema
 * @param configId      - configuration number to which the device description belongs
 *                      (must be identical to the one from discovery message)
 * @param specVersion   - @see SpecVersion
 * @param device        - @see Device
 * @param language      - content description language specified by device
 *
 * @see "https://openconnectivity.org/upnp-specs/UPnP-arch-DeviceArchitecture-v2.0-20200417.pdf", ch.2.3
 */
data class XmlDeviceDescription(
    val specVersion: SpecVersion,
    val systemVersion: SystemVersion? = null,
    val device: DeviceDescription,
    var urn: String? = null,
    var configId: Int? = null,
    var language: String = "en"
) {
    companion object  {
        /**
         * Facilitates fast and flexible deserialization and conditional validation.
         */
        fun fromXml(xml: XmlElement): XmlDeviceDescription {
            var specVersionO by Delegates.notNull<SpecVersion>()
            var systemVersionO: SystemVersion? = null
            var deviceO by Delegates.notNull<DeviceDescription>()
            var urnS: String? = xml.attributes?.get("xmlns")
            var configIdI: Int? = xml.attributes?.get("configId")?.toInt()

            xml.children?.forEach {
                when (it.tag) {
                    "specVersion" -> specVersionO = SpecVersion.Companion.fromXml(it)
                    "systemVersion" -> systemVersionO = SystemVersion.Companion.fromXml(it)
                    "device" -> deviceO = DeviceDescription.Companion.fromXml(it)
                    else -> Logger.info("Unexpected tag ${it.tag}")
                }
            }
            return XmlDeviceDescription(specVersionO, systemVersionO, deviceO, urnS, configIdI)
        }

        fun XmlElement.toXmlDeviceDescription(): XmlDeviceDescription = fromXml(this)
    }
}
